// #include <iostream>
// #include <vector>
// #include <algorithm>
// using namespace std;
// vector<pair<char, char>> a;    
// vector<string> nums;
// int n;
// vector<bool> visit(1100);
// vector<vector<string>> ans;
// vector<string> temp;
// void dfs(int x) {
//     if(temp.size() == n) {
//         ans.push_back(temp);
//     }
//     for(int i = 0; i < n; i++) {
//         if(!visit[i] && a[x].second == a[i].first) {
//             temp.push_back(nums[i]);
//             visit[i] = true;
//             dfs(i);
//             temp.pop_back();
//             visit[i] = false;
//         }
//     }
// }
// int main() {
//     cin >> n;
//     for(int i = 1; i <= n; i++) {
//         string t;
//         cin >> t;
//         nums.push_back(t);
//         a.push_back(make_pair(t[0], t[t.size() - 1]));
//     }
//     for(int i = 0; i < n; i++) {
//         visit[i] = true;
//         temp.push_back(nums[i]);
//         dfs(i);
//         visit[i] = false;
//         temp.pop_back();
//     }
//     if(ans.empty()) {
//         cout << "***" << endl;
//         return 0;
//     }
//     vector<string> ret;
//     for(auto& s: ans)
//     {
//         string x;
//         for(int i = 0; i < s.size(); i++) {
//             if(i == s.size() - 1) {
//                 x += s[i];
//                 break;
//             }
//             x += s[i];
//             x += ".";
//         }
//         ret.push_back(x);
//     }
    
//     sort(ret.begin(), ret.end());
//     cout << ret[0] << endl;
//     return 0;
// }

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <stack>
using namespace std;

const int N = 26; // 26个小写字母

vector<string> words;
vector<vector<int>> graph(N); // 邻接表，存储单词索引
vector<int> inDegree(N, 0), outDegree(N, 0);
vector<int> path;
vector<bool> used;

// 检查欧拉路径条件
bool hasEulerPath() {
    int start = 0, end = 0;
    for (int i = 0; i < N; i++) {
        int diff = outDegree[i] - inDegree[i];
        if (diff == 1) start++;
        else if (diff == -1) end++;
        else if (diff != 0) return false;
        
        if (start > 1 || end > 1) return false;
    }
    return true;
}

// 找到起点
int findStartNode() {
    int start = -1;
    for (int i = 0; i < N; i++) {
        if (outDegree[i] == inDegree[i] + 1) return i;
        if (outDegree[i] > 0 && start == -1) start = i;
    }
    return start;
}

// Hierholzer算法寻找欧拉路径
void dfs(int u) {
    while (!graph[u].empty()) {
        int wordIdx = graph[u].back();
        graph[u].pop_back();
        dfs(words[wordIdx].back() - 'a');
        path.push_back(wordIdx);
    }
}

int main() {
    int n;
    cin >> n;
    words.resize(n);
    used.resize(n, false);
    
    // 读入单词并统计度数
    for (int i = 0; i < n; i++) {
        cin >> words[i];
        int u = words[i][0] - 'a';
        int v = words[i].back() - 'a';
        outDegree[u]++;
        inDegree[v]++;
    }
    
    // 按字典序排序单词
    sort(words.begin(), words.end());
    
    // 构建图（按字典序逆序插入，这样dfs时从字典序小的开始）
    for (int i = n - 1; i >= 0; i--) {
        int u = words[i][0] - 'a';
        graph[u].push_back(i);
    }
    
    // 检查是否存在欧拉路径
    if (!hasEulerPath()) {
        cout << "***" << endl;
        return 0;
    }
    
    // 找到起点并开始DFS
    int start = findStartNode();
    dfs(start);
    
    // 检查是否使用了所有单词
    if (path.size() != n) {
        cout << "***" << endl;
        return 0;
    }
    
    // 输出结果（路径是逆序的，需要反转）
    reverse(path.begin(), path.end());
    for (int i = 0; i < path.size(); i++) {
        if (i > 0) cout << ".";
        cout << words[path[i]];
    }
    cout << endl;
    
    return 0;
}